package app;

import java.util.ArrayList;
import java.util.Iterator;

import org.grlea.log.SimpleLogger;

import app.gui.Drawable;

import cluster.Duster;

import color.Color;

import processing.core.PApplet;

public class ClusterDrawer implements Drawable{
	private final SimpleLogger log = new SimpleLogger(ClusterDrawer.class);
	public ClusterDrawer(float x, float y, float w, float h, Duster<Color> root){
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h;
		this.root = root;
	}
	
	
	float x, y, w, h;
	Duster<Color> root;
	float vSpacingRatio = 1.5f;
	float hSpacingRatio = 0.1f;
	float hSpacingMax = 10;
	float hSpacingMin = 1;
	
	public void initTopDown(){
		float h = this.h / (root.getHeight() * vSpacingRatio);
		setTopDown(x, y, w, h, root);
	}
	
	private void setTopDown(float x, float y, float w, float h, Duster<Color> current){
		current.setDrawRect(x, y, w, h); 
		if(!current.isLeaf()){
			int totalChildren = current.getLeafs().size();
			float wRatio = w / totalChildren;
			y += h * vSpacingRatio;
			Iterator<Duster<Color>> i = current.children.iterator();
			while(i.hasNext()){
				Duster<Color> duster = i.next();

				if(!duster.isLeaf()){
					log.ludicrousObject("DusterSize", duster.getChildren().size());
					w = wRatio * duster.getLeafs().size();
				}
				else w = wRatio;
				setTopDown(x, y, w, h, duster);
				x += w;
			}
		}
		log.exit("draw(PApplet pa ...)");
	}
	
	private void setByMaxDev(float x, float y, float w, float h, Duster<Color> current){
		current.setDrawRect(x, y, w, h); 
		if(!current.isLeaf()){
			float totalDev = 0;
			Iterator<Duster<Color>> i = current.children.iterator();
			int leafs = 0;
			while(i.hasNext()){
				Duster<Color> next = i.next();
				if(next.isLeaf())
					leafs++;
				else
					totalDev += next.maxDev;
			}
			float leafSize = Math.max(1, totalDev / (current.children.size()*2f));
			totalDev += leafs * leafSize;
			float wRatio = w / totalDev;
			y += h * vSpacingRatio;
			Iterator<Duster<Color>> k = current.children.iterator();
			while(k.hasNext()){
				Duster<Color> duster = k.next();
				if(duster.isLeaf())
					w = leafSize;
				else
					w = wRatio * duster.maxDev;
				setTopDown(x, y, w, h, duster);
				x += w;
			}
		}
		log.exit("draw(PApplet pa ...)");
	}
	
	public void initByMaxDev(){
		float h = this.h / (root.getHeight() * vSpacingRatio);
		setByMaxDev(x, y, w, h, root);
	}
	
	private void setBtmUp(float x, float y, float w, float h, float _h, Duster<Color> current){
		current.setDrawRect(x, y, w, h); 
		log.ludicrous("rect: " + x+", " +y+" "+w+" "+h);
		if(!current.isLeaf()){
			int totalChildren = current.getLeafs().size();
			float wRatio = w / totalChildren;
			
			Iterator<Duster<Color>> i = current.children.iterator();
			while(i.hasNext()){
				Duster<Color> duster = i.next();
				y = this.y + duster.getDepth() * h * vSpacingRatio;
				_h = (this.y + this.h - duster.getHeight() * h * vSpacingRatio) - y;
				log.debug("dpt "+ duster.getDepth() + " hgt " + duster.getHeight() + " y " + y + " _h " + h);
				log.debugObject("_h", _h);
				if(!duster.isLeaf()){
					//log.ludicrousObject("DusterSize", duster.getChildren().size());
					w = wRatio * duster.getLeafs().size();
				}
				else w = wRatio;
				setBtmUp(x, y, w, h, _h, duster);
				x += w;
			}
		}
		log.exit("draw(PApplet pa ...)");
	}
	
	public void drawBtmUpOLD(PApplet pa){
		int levels = root.getHeight(); 
		int total = root.getLeafs().size();
		float h = this.h / (levels * vSpacingRatio);

		for(int i = levels-1; i >= 0; i--){
			Iterator<Duster<Color>> list = root.getPredesessors(i).iterator();
			float y = this.y + h * (levels - 1 - i);
			float x = this.x;
			while(list.hasNext()){
				Duster<Color> duster = list.next();
				
				float w = this.w * duster.getLeafs().size() / total;
				duster.centroid.fill(pa);
				pa.rect(x, y, w, h);
				x += w;
			}
			
			
		}
		
	}
	
	public void setContained(Duster<Color> root, int xy, float x, float y, float w, float h){
		if(!root.isLeaf()){
			root.setDrawRect(0, 0, 0, 0);
			if(xy%2 == 0) 
				w = w / root.children.size();
			else
				h = h / root.children.size();
			xy++;
			Iterator<Duster<Color>> i = root.children.iterator();
			while(i.hasNext()){
				setContained(i.next(), xy, x, y, w, h);
				if(xy%2 == 1)
					x += w;
				else 
					y += h;
			}
		}
		else root.setDrawRect(x, y, w, h);
	}
	
	public void draw(PApplet pa){
		root.draw(pa);
	}
	
	


}
